package com.iteaj.network.server.component;

import com.iteaj.network.*;
import com.iteaj.network.codec.DeviceMessageDecoder;
import com.iteaj.network.config.ConnectProperties;
import com.iteaj.network.message.UnParseBodyMessage;
import com.iteaj.network.server.AbstractTcpServer;
import com.iteaj.network.server.DeviceServerComponent;
import com.iteaj.network.server.IotSocketServer;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import org.springframework.core.GenericTypeResolver;

/**
 * create time: 2021/2/20
 *
 * @author iteaj
 * @since 1.0
 */
public abstract class TcpDecoderComponent<M extends UnParseBodyMessage> extends DeviceServerComponent
        implements IotSocketServer, IotProtocolFactory<M>, DeviceMessageDecoder<M, ByteBuf> {

    private ConnectProperties connectProperties;
    private TcpServerWrapper deviceServerWrapper;
    private ProtocolFactoryDelegation delegation;

    public TcpDecoderComponent(ConnectProperties connectProperties) {
        this.connectProperties = connectProperties;
        this.deviceServerWrapper = new TcpServerWrapper(connectProperties);
        this.delegation = new ProtocolFactoryDelegation(this);
    }

    @Override
    public abstract String getName();

    @Override
    public int port() {
        return this.connectProperties.getPort();
    }

    @Override
    public ConnectProperties config() {
        return this.connectProperties;
    }

    @Override
    protected IotSocketServer createDeviceServer() {
        return this.deviceServerWrapper;
    }

    @Override
    protected IotProtocolFactory createProtocolFactory() {
        return this.delegation;
    }

    @Override
    public void init(Object... args) {
        initChannelPipeline((ChannelPipeline) args[0]);
    }

    @Override
    public void initChannelPipeline(ChannelPipeline pipeline) {
        deviceServerWrapper.initChannelPipeline(pipeline);
    }

    @Override
    public abstract M decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception;

    @Override
    public Class<M> messageClass() {
        Class<?> aClass = GenericTypeResolver.resolveTypeArgument(getClass()
                , TcpDecoderComponent.class);
        return (Class<M>) aClass;
    }

    @Override
    public AbstractProtocol get(String key) {
        return this.delegation.get(key);
    }

    @Override
    public AbstractProtocol add(String key, Protocol val) {
        return this.delegation.add(key, val);
    }

    @Override
    public AbstractProtocol add(String key, Protocol protocol, long timeout) {
        return this.delegation.add(key, protocol, timeout);
    }

    @Override
    public AbstractProtocol remove(String key) {
        return this.delegation.remove(key);
    }

    @Override
    public boolean isExists(String key) {
        return this.delegation.isExists(key);
    }

    @Override
    public Object getStorage() {
        return this.delegation.getStorage();
    }

    protected class TcpServerWrapper extends AbstractTcpServer {

        @Deprecated
        public TcpServerWrapper(int port) {
            super(port);
        }

        public TcpServerWrapper(ConnectProperties serverConfig) {
            super(serverConfig);
        }

        @Override
        public ChannelInboundHandlerAdapter getMessageDecoder() {
            return TcpDecoderComponent.this.getMessageDecoder();
        }
    }

}
